package org.springframework.beans.factory.support;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author:刘仁有
 * @desc:
 * @email:953506233@qq.com
 * @data:2019/12/15
 */
public final class PostProcessorRegistrationDelegate {

    /**
     *
     * @param beanFactory
     * @param beanFactoryPostProcessors 这个是我们手动app.addBeanFactoryPostProcessors产生的，源码里会回调你写的这个后置处理器
     * @throws Exception
     */
    public static void invokeBeanFactoryPostProcessors(DefaultListableBeanFactory beanFactory,
                        List<BeanFactoryPostProcessor> beanFactoryPostProcessors) throws Exception {

        if(beanFactory instanceof BeanDefinitionRegistry){

            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

            //手动app.addBeanFactoryPostProcessor中的BeanFactoryPostProcessor
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

            //手动app.addBeanFactoryPostProcessor中的BeanDefinitionRegistryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            //处理手动addBeanFactoryPostProcessor的
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    //回调你写的BeanDefinitionRegistryPostProcessor
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }
            //系统的ConfigurationClassPostProcessor
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class);
            for (String ppName : postProcessorNames) {
                currentRegistryProcessors.add((BeanDefinitionRegistryPostProcessor) beanFactory.getBean(ppName));
            }

            registryProcessors.addAll(currentRegistryProcessors);
            //currentRegistryProcessors只有一个数据 这行代码就是做解析Config的
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

            currentRegistryProcessors.clear();
            //回调
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            //回调
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }
    }

    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }


    private static void invokeBeanFactoryPostProcessors(
            Collection<? extends BeanFactoryPostProcessor> postProcessors, DefaultListableBeanFactory beanFactory) {

        for (BeanFactoryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    }

    private static void registerBeanPostProcessors(
            DefaultListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
        for (BeanPostProcessor postProcessor : postProcessors) {
            beanFactory.registerBeanPostProcessor(postProcessor);
        }
    }

    public static void registerBeanPostProcessors(DefaultListableBeanFactory beanFactory) throws Exception {
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true);
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();

        for (String ppName : postProcessorNames) {
                BeanPostProcessor pp = (BeanPostProcessor) beanFactory.getBean(ppName);
                internalPostProcessors.add(pp);
        }

        registerBeanPostProcessors(beanFactory,internalPostProcessors);
    }
}
